#pragma once

#include <iostream>
#include <poll.h>
#include <unistd.h>
#include "Sock.hpp"

#define FD_NONE -1
#define FD_USING -2
#define WAITTIME 1000

class PollServer
{
public:
    PollServer(std::string ip = "0.0.0.0", uint16_t port = 8080, int nfds = 100)
        : _nfds(nfds)
    {
        _listensock = sock.Socket();
        sock.Bind(_listensock, ip, port);
        sock.Listen(_listensock);

        _fds = new struct pollfd[_nfds];
        for (int i = 0; i < _nfds; i++)
        {
            _fds[i].fd = FD_NONE;
            _fds[i].events = _fds[i].revents = 0;
        }
        _fds[0].fd = _listensock;
        _fds[0].events = POLLIN;
    }

    ~PollServer()
    {
        if (_fds)
        {
            delete[] _fds;
        }
        if (_listensock > 0)
            close(_listensock);
    }

    void Start()
    {
        while (true)
        {
            Print();
            int ret = poll(_fds, _nfds, WAITTIME);
            if (ret > 0)
            {
                std::cout << "success " << std::endl;
                HandlerFunc();
            }
            else if (ret == 0)
            {
                std::cout << "time wait " << std::endl;
            }
            else 
            {
                std::cerr << "error: " << errno << "  strerror: " << strerror(errno) << std::endl;
            }
        }
    }

    void HandlerFunc()
    {
        for (int i = 0; i < _nfds; i++)
        {
            if (_fds[i].fd == FD_NONE)
            {
                break;
            }

            if (i == 0 && (_fds[i].revents & POLLIN == 1))
            {
                //获取新连接
                Accept();
            }
            else if (_fds[i].revents & POLLIN == 1)
            {
                //读取数据
                Recv(i);
            }
        }
    }

    void Accept()
    {
        std::string buffer;
        std::string ip;
        uint16_t port;

        int serverSock = sock.Accept(_listensock, &ip, &port);
        if (serverSock > 0)
        {
            //链接建立成功
            std::cout << "[" << ip << "  " << port << "]  链接建立成功" << std::endl;

            int i = 0;
            for (i = 1; i < _nfds; i++)
            {
                if (_fds[i].fd == FD_NONE || _fds[i].fd == FD_USING)
                {
                    _fds[i].fd = serverSock;
                    _fds[i].events = POLLIN;
                    break;
                }
            }
            if (i == _nfds)
            {
                //文件描述符满了
                std::cout << "文件描述符已满，无法添加" << std::endl;
                //扩容?
            }
        }
    }

    void Recv(int posi)
    {
        std::string buffer;
        int n = sock.Revc(_fds[posi].fd, buffer);
        if (n > 0)
        {
            std::cout << "read success  message: " << buffer;
        }
        else if (n == 0)
        {
            //对方关闭了文件描述符
            std::cout << "you close fd, me too" << std::endl;
            close(_fds[posi].fd);
            _fds[posi].fd = FD_USING;
            _fds[posi].events = _fds[posi].revents = 0;
        }
    }

    void Print()
    {
        std::cout << "_fds[ ";
        for (int i = 0; i < _nfds; i++)
        {
            if (_fds[i].fd == FD_NONE)
                break;
            if (_fds[i].fd != FD_USING)
                std::cout << _fds[i].fd << " ";
        }
        std::cout << "]" << std::endl;
    }

private:
    struct pollfd* _fds;
    int _nfds;

    int _listensock;
    Sock sock;
};